package top.codedance.iotp.client.net.manage;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import top.codedance.iotp.client.ClientApplication;
import top.codedance.iotp.common.entity.CommandTeam;
import top.codedance.iotp.common.entity.PluginResultEntity;
import top.codedance.iotp.common.executer.CommonClientPluginExecuter;
import org.apache.log4j.Logger;

import java.io.*;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.Map;
import java.util.Set;
import java.util.UUID;

public class ManageService implements Runnable {
    private Logger logger = ClientApplication.getLogger(ManageService.class);
    private InputStream in;
    private OutputStream out;
    private String startStr = "<![[";
    private String endStr = "]]-->\n";

    public ManageService(InputStream in, OutputStream out) {
        this.in = in;
        this.out = out;
    }

    @Override
    public void run() {
        BufferedReader br = new BufferedReader(new InputStreamReader(in, Charset.forName(System.getProperty("sun.jnu.encoding"))));
        final BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(out, Charset.forName(System.getProperty("sun.jnu.encoding"))));
        while (true) {
            try {
                StringBuilder sb = new StringBuilder();
                String line;
                while ((line = br.readLine()) != null) {
                    sb.append(line);
                    try{
                        final JSONObject command = JSON.parseObject(sb.toString());
                        logger.debug("Client: " + command.toJSONString());
                        if(command.containsKey("plugin")){
                            short plugin = command.getShort("plugin");
                            final byte[] body = command.getJSONObject("client").toJSONString().getBytes(StandardCharsets.UTF_8);
                            Set<Map.Entry<CommandTeam, CommonClientPluginExecuter>> entries2 = ClientApplication.syncExcuters.entrySet();
                            for (Map.Entry<CommandTeam, CommonClientPluginExecuter> entry : entries2) {
                                CommandTeam commandTeam = entry.getKey();
                                if (plugin == commandTeam.getRequestCommand()) {
                                    final CommonClientPluginExecuter commonExecuter = entry.getValue();
                                    commonExecuter.setIniConfig(ClientApplication.ini);
                                    ClientApplication.syncWorkerPool.submit(() -> {
                                        PluginResultEntity pluginResultEntity = commonExecuter.exec(body, UUID.randomUUID().toString());
                                        byte[] results = JSONObject.toJSONString(pluginResultEntity, SerializerFeature.WriteMapNullValue, SerializerFeature.WriteNullStringAsEmpty).getBytes(StandardCharsets.UTF_8);
                                        try {
                                            StringBuilder tmpSb = new StringBuilder();
                                            tmpSb.append(startStr);
                                            tmpSb.append(new String(results, StandardCharsets.UTF_8));
                                            tmpSb.append(endStr);
                                            Thread.sleep(200);
                                            bw.write(tmpSb.toString());
                                            bw.flush();
                                        }catch (Exception e){
                                            logger.debug(e.getMessage());
                                        }
                                    });
                                    break;
                                }
                            }
                        }
                        sb = new StringBuilder();
                    }catch (Exception e){
                        logger.debug(e.getMessage());
                    }
                }
            } catch (Exception e) {
                logger.debug(e.getMessage());
            }
            try {
                Thread.sleep(100);
            } catch (Exception e) {
            }
        }
    }
}
